using System;
using System.Linq;
using System.Linq.Expressions;
using System.Data.Entity;
using System.Collections.Generic;
using Pay.IService;
using Pay.DTO;
using Pay.Data;
using Pay.Service.Cache;
using Pay.Core;

namespace Pay.Service {
	public class RoleService : ServiceBase, IRoleService, IDisposable {
		private IUnitOfWork _iUnitOfWork;
		public RoleService(IUnitOfWork iUnitOfWork) : base(iUnitOfWork) {
			_iUnitOfWork = iUnitOfWork;
		}

		public IEnumerable<role_dto> GetAll(string name = "") {
			Expression<Func<Role, bool>> filter = c => true;
			if (!string.IsNullOrEmpty(name))
				filter = filter.And(c => c.Name.Contains(name));
			return context.Roles.Where(filter).FromCache<Role, role_dto>("Role");
		}

		public role_dto Get(long id) {
			return context.Roles.Where(c => c.Id == id).FromCacheFirstOrDefault<Role, role_dto>("Role");
		}

		public int Add(role_dto dto) {
			var model = dto.ToDtoObject<Role>();
			dto.feature_ids.ForEach(filter_id => {
				model.RoleFeatures.Add(new RoleFeature { FeatureId = filter_id });

				var parentIds = context.Features.Find(filter_id).Path.Split('-');
				if (parentIds.Length > 0 && parentIds[0] != string.Empty) {
					foreach (var parentId in parentIds) {
						if (!model.RoleFeatures.Any(c => c.FeatureId == long.Parse(parentId)))
							model.RoleFeatures.Add(new RoleFeature { FeatureId = long.Parse(parentId) });
					}
				}
				var children = context.Features.Where(c => c.ParentId == filter_id);
				foreach (var child in children)
					model.RoleFeatures.Add(new RoleFeature { FeatureId = child.Id });
			});
			context.Roles.Add(model);
			int result = _iUnitOfWork.Commit("Role");
			return result;
		}

		public int Update(role_dto dto) {
			var model = context.Roles.FindById(dto.id);
			dto.ToDtoObject<Role>(model);
			if (dto.feature_ids.Count > 0) {
                var data_ids = model.RoleFeatures.Select(c => c.FeatureId).CopyToList();
                //新增
                dto.feature_ids.Except(data_ids).DataForEach(filter_id => {
                    model.RoleFeatures.Add(new RoleFeature { RoleId = dto.id, FeatureId = filter_id });

                    var parentIds = context.Features.Find(filter_id).Path.Split('-');
                    if (parentIds.Length > 0 && parentIds[0] != string.Empty) {
                        foreach (var parentId in parentIds) {
                            if (!model.RoleFeatures.Any(c => c.FeatureId == long.Parse(parentId)))
                                model.RoleFeatures.Add(new RoleFeature { FeatureId = long.Parse(parentId) });
                        }
                    }
                    var children = context.Features.Where(c => c.ParentId == filter_id);
                    foreach (var child in children)
                        model.RoleFeatures.Add(new RoleFeature { FeatureId = child.Id });
                });
                //删除
                var friids = new List<long>();
                data_ids.Except(dto.feature_ids).DataForEach(filter_id => {
                    var item = model.RoleFeatures.FirstOrDefault(c => c.FeatureId == filter_id);
                    long f_pid = item.Feature.ParentId;
                    if (context.Entry(item).State != EntityState.Deleted) {
                        context.Entry(item).State = EntityState.Deleted;
                        //如果有同级的菜单有打通时，不可以执行下面的上级删除
                        var prevs = context.Features.Where(c => c.ParentId == f_pid && c.Id != filter_id).Select(c => c.Id).CopyToList();
                        var has = data_ids.Intersect(prevs).Count();
                        if (has == 0) {
                            var parentIds = context.Features.Find(filter_id).Path.Split('-');
                            if (parentIds.Length > 0 && parentIds[0] != string.Empty) {
                                foreach (var parentId in parentIds) {
                                    var deled = model.RoleFeatures.FirstOrDefault(c => c.FeatureId == long.Parse(parentId));
                                    if (deled != null) {
                                        if (deled.Feature.ParentId == 0) {
                                            friids.Add(deled.Feature.Id);
                                            continue;
                                        }
                                        context.Entry(deled).State = EntityState.Deleted;
                                    }
                                }
                            }
                        }
                    }
                    var children = context.Features.Where(c => c.ParentId == filter_id);
                    foreach (var child in children) {
                        var deled = model.RoleFeatures.FirstOrDefault(c => c.FeatureId == child.Id);
                        context.Entry(deled).State = EntityState.Deleted;
                    }
                });
                if (friids.Count > 0) {
                    foreach (var id in friids) {
                        if (!context.RoleFeatures.Any(c => c.Feature.ParentId == id)) {
                            var deled = model.RoleFeatures.FirstOrDefault(c => c.FeatureId == id);
                            context.Entry(deled).State = EntityState.Deleted;
                        }
                    }
                }
            } else {
				//如果原来有数据，删除
				if (model.RoleFeatures.Count > 0)
					model.RoleFeatures.DataForEach(item => { context.Entry(item).State = EntityState.Deleted; });
			}
			int result = _iUnitOfWork.Commit("Role");
			return result;
		}

		public int Delete(long id) {
			var model = context.Roles.FindById(id);
			context.Roles.Remove(model);
			int result = _iUnitOfWork.Commit("Role");
			return result;
		}
	}
}
